﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.Data;
using System.Xml;
using System.Text.RegularExpressions;

namespace Cleware.Debit3.Tools.EdmUtil
{
    public class Edm
    {
        #region Constants
        private const string NS_SSDL = "http://schemas.microsoft.com/ado/2009/02/edm/ssdl";     //3.5 - http://schemas.microsoft.com/ado/2006/04/edm/ssdl
        private const string NS_CSDL = "http://schemas.microsoft.com/ado/2008/09/edm";          //3.5 - http://schemas.microsoft.com/ado/2006/04/edm
        private const string NS_MSL = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";   //3.5 - urn:schemas-microsoft-com:windows:storage:mapping:CS
        #endregion

        #region Fields & properties
        public Parameters Parameters { get; set; }
        public string ConceptualModelsSchemaNameSpace { get; set; }
        public string StorageModelsSchemaNameSpace { get; set; }
        #endregion

        #region Initialization
        public Edm(Parameters parameters)
        {
            this.Parameters = parameters;
            ConceptualModelsSchemaNameSpace = InitConceptualModelsSchemaNamespace();
            StorageModelsSchemaNameSpace = InitStorageModelsSchemaNamespace();

        }
        #endregion

        #region Methods
        public void Start(Parameters parameters)
        {
            this.Parameters = parameters;
            Start();
        }
        public void Start()
        {
            GetAllDescriptions();
            BackupEdmx();

            List<Function> functionList = new List<Function>();
            List<FunctionImport> functionImportList = new List<FunctionImport>();
            List<FunctionResult> functionResultList = new List<FunctionResult>();
            List<FunctionImportMapping> functionImportMappingList = new List<FunctionImportMapping>();

            #region Process functions
            using (TextReader reader = File.OpenText(Parameters.Ssdl))
            {
                XDocument ssdl = XDocument.Load(reader);
                if (ssdl != null)
                {
                    XNamespace xns = ssdl.Root.GetDefaultNamespace();
                    var functions = ssdl.Root
                                        .Elements()
                                        .Where(f => (f.Name == "{" + xns.NamespaceName + "}Function") 
                                            && (f.Attribute("Name").Value.Substring(0, 3) != "dt_") 
                                            && (f.Attribute("Name").Value.Substring(0, 3) != "sp_") 
                                            && (f.Attribute("Name").Value.Substring(0, 3) != "fn_"));

                    if(!Config.Instance.IgnoreStoredProcedures)
                    foreach (XElement function in functions)
                    {
                        string spName = (string)function.Attribute("Name");

                        if ((Parameters.SPList != null) && (!Parameters.SPList.Contains(spName)))
                        {
                            Logger.Instance.Log(Logger.LogType.Skipped, string.Format("{0} - nem feldolgozandó", spName));
                            continue;
                        }

                        //kivételek + info a log-ba
                        if ((Parameters.Exclusions != null) && Parameters.Exclusions.Contains(spName))
                        {
                            Logger.Instance.Log(Logger.LogType.Skipped, string.Format("{0} - kihagyva", spName));
                            continue;
                        }

                        Console.WriteLine(spName);

                        #region Function
                        Function f = new Function()
                        {
                            Name = function.Attribute("Name") == null ? "" : function.Attribute("Name").Value,
                            ReturnType = function.Attribute("ReturnType") == null ? "" : function.Attribute("ReturnType").Value,
                            Aggregate = function.Attribute("Aggregate") == null ? "" : function.Attribute("Aggregate").Value,
                            BuiltIn = function.Attribute("BuiltIn") == null ? "" : function.Attribute("BuiltIn").Value,
                            StoreFunctionName = function.Attribute("StoreFunctionName") == null ? "" : function.Attribute("StoreFunctionName").Value,
                            NiladicFunction = function.Attribute("NiladicFunction") == null ? "" : function.Attribute("NiladicFunction").Value,
                            IsComposable = function.Attribute("IsComposable") == null ? "" : function.Attribute("IsComposable").Value,
                            ParameterTypeSemantics = function.Attribute("ParameterTypeSemantics") == null ? "" : function.Attribute("ParameterTypeSemantics").Value,
                            Schema = function.Attribute("Schema") == null ? "" : function.Attribute("Schema").Value
                        };

                        //parameters
                        #region Parameters
                        var baseParameters = function.Descendants(xns + "Parameter");
                        foreach (XElement baseParameter in baseParameters)
                        {
                            f.Parameters.Add(new Function.Parameter()
                            {
                                Name = baseParameter.Attribute("Name") == null ? "" : baseParameter.Attribute("Name").Value,
                                Type = baseParameter.Attribute("Type") == null ? "" : baseParameter.Attribute("Type").Value,
                                Mode = baseParameter.Attribute("Mode") == null ? "" : baseParameter.Attribute("Mode").Value,
                                MaxLength = baseParameter.Attribute("MaxLength") == null ? "" : baseParameter.Attribute("MaxLength").Value,
                                Precision = baseParameter.Attribute("Precision") == null ? "" : baseParameter.Attribute("Precision").Value,
                                Scale = baseParameter.Attribute("Scale") == null ? "" : baseParameter.Attribute("Scale").Value
                            });
                        }
                        #endregion
                        functionList.Add(f);
                        #endregion

                        #region FunctionResults
                        FunctionResult functionResult = GetResultSchema(spName, function);
                        if (functionResult != null)
                            functionResultList.Add(functionResult);

                        #region FunctionImports
                        FunctionImport fi = new FunctionImport()
                        {
                            Name = spName,
                            ReturnType = functionResult == null ? "" : string.Format(Constants.FUNCTIONIMPORT_RETURNTYPE, ConceptualModelsSchemaNameSpace, spName)
                        };

                        #region Parameters
                        foreach (Function.Parameter parameter in f.Parameters)
                        {
                            fi.Parameters.Add(new FunctionImport.Parameter()
                            {
                                Name = parameter.Name,
                                Mode = parameter.Mode,
                                Type = GetEDMSimpleType(parameter.Type)
                            });
                        }
                        #endregion

                        functionImportList.Add(fi);
                        #endregion FunctionImports

                        #region FunctionImportMappings
                        functionImportMappingList.Add(GetFunctionImportMapping(spName, functionResult));
                        #endregion FunctionImportMappings
                     
                        #endregion FunctionResults
                    }
                }
            }
            #endregion

            PrepareEdmx();
            UpdateEDMX(functionList, functionImportList, functionResultList, functionImportMappingList);
        }

        private void GetAllDescriptions()
        {
            Logger.Instance.Log(Logger.LogType.Info, string.Format("DB elem leírások lekérdezése (-> {0})...", Constants.DESCRIPTION_FILE));
            if (File.Exists(Constants.DESCRIPTION_FILE))
            {
                File.Delete(Constants.DESCRIPTION_FILE);
            }

            DA da = new DA(Parameters.ConnectionString);

            string desc = da.GetAllDescriptionFromDatabase(Parameters.XmlDescription);
            File.WriteAllText(Constants.DESCRIPTION_FILE, desc, Encoding.UTF8);
            Logger.Instance.Log(Logger.LogType.Info, "DB elem leírások lekérdezése...KÉSZ\n");
        }
        private string GetEDMSimpleType(string baseType)
        {
            string retval = baseType;

            switch (baseType.ToLower())
            {
                case "int":
                    retval = "Int32";
                    break;
                case "bit":
                    retval = "Boolean";
                    break;
                case "smallint":
                    retval = "Int16";
                    break;
                case "decimal":
                    retval = "Decimal";
                    break;
                case "string":
                case "varchar":
                case "nvarchar":
                case "varchar(max)":
                case "nvarchar(max)":
                    retval = "String";
                    break;
                case "datetime":
                    retval = "DateTime";
                    break;
                case "byte":
                    retval = "Byte";
                    break;
                case "boolean":
                    retval = "Boolean";
                    break;

                default:
                    Logger.Instance.Log(string.Format("WARNING - unknown base type (from StorageModel Function): {0}", baseType));
                    break;
            }


            return retval;
        }
        private string InitConceptualModelsSchemaNamespace()
        {
            string retval = Constants.DEFAULT_CONCEPTUALMODELSSCHEMANAME;

            try
            {
                XDocument xdoc = XDocument.Load(Parameters.Edmx);

                XNamespace ns = "http://schemas.microsoft.com/ado/2008/09/edm";
                var schema = xdoc.Descendants(ns + "Schema")
                                .FirstOrDefault();

                if (schema != null)
                    retval = schema.Attribute("Namespace").Value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            return retval;
        }
        private string InitStorageModelsSchemaNamespace()
        {
            string retval = Constants.DEFAULT_STORAGEMODELSSCHEMANAME;

            try
            {
                XDocument xdoc = XDocument.Load(Parameters.Edmx);

                XNamespace ns = "http://schemas.microsoft.com/ado/2009/02/edm/ssdl";
                var schema = xdoc.Descendants(ns + "Schema")
                                .FirstOrDefault();
                if (schema != null)
                    retval = schema.Attribute("Namespace").Value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            return retval;
        }
        private FunctionResult GetResultSchema(string spName, XElement function)
        {
            FunctionResult retval = null;
            DA da = new DA(Parameters.ConnectionString);

            List<string> parameters = new List<string>();

            var sqlParameters = function.Descendants();
            foreach (XElement parameter in sqlParameters)
                parameters.Add(parameter.Attribute("Name").Value);

            DataSet resultSchema = da.GetResultSchema(spName, parameters);
            if (resultSchema != null)
            {
                retval = GenerateResult(spName, resultSchema);
            }
            return retval;
        }
        private FunctionResult GenerateResult(string spName, DataSet resultSchema)
        {
            FunctionResult retval = null;
            if ((resultSchema == null) || (resultSchema.Tables.Count == 0))
                return retval;
            retval = new FunctionResult()
            {
                Name = string.Format(Constants.RESULTNAME, spName)
            };

            List<string> multiplePropNames = new List<string>();
            foreach (DataRow row in resultSchema.Tables[0].Rows)
            {
                bool isHidden;
                string val = row["IsHidden"].ToString();
                if (bool.TryParse(val, out isHidden) && isHidden)
                {
                    continue;
                }

                Type t = row["DataType"] as Type;
                string name = row["ColumnName"].ToString();

                //egyező mezőnevek keresése
                var s = retval.Properties.Find(p => p.Name == name);
                if ((s != null) && (!multiplePropNames.Contains(name)))
                    multiplePropNames.Add(name);


                FunctionResult.Property prp = new FunctionResult.Property()
                {
                    Type = t.Name,
                    Name = name,
                    Nullable = (bool)row["AllowDBNull"],
                    MaxLength = (t == typeof(string)) ? (int?)(row["ColumnSize"]) : null,
                    Precision = ((t == typeof(DateTime)) ? (int?)23 : null)
                };

                if (multiplePropNames.Contains(name))
                {
                    //ha már van ilyen nevű mező, akkor sorszámozza őket!
                    int i = 1;
                    
                    while (retval.Properties.FindIndex(p => p.Name == string.Format("{0}_{1}", name, i)) > -1) 
                    {
                        i++;
                    }
                    prp.Name = string.Format("{0}_{1}", name, i);
                }

                retval.Properties.Add(prp);
                if (prp.Name != prp.NormalizedName)
                    Logger.Instance.Log(Logger.LogType.Warning, string.Format("\thibás mezőnév: {0}", prp.Name));


            }
            if (multiplePropNames.Count > 0)
            {
                string s = multiplePropNames[0];
                for (int i=1; i<multiplePropNames.Count; i++)
                    s += "," + multiplePropNames[i];
                Logger.Instance.Log(Logger.LogType.Warning, string.Format("\tIsmétlődő mezőnevek: {0}", s));
            }
            return retval;
        }
        private FunctionImportMapping GetFunctionImportMapping(string spName, FunctionResult functionResult)
        {
            FunctionImportMapping retval = null;
            retval = new FunctionImportMapping(ConceptualModelsSchemaNameSpace, spName, functionResult)
            {
                FunctionImportName = spName,
                FunctionName = string.Format(Constants.FUNCTIONIMPORTMAPPING_FUNCTIONNAME, StorageModelsSchemaNameSpace, spName)
            };
            return retval;
        }

        private void UpdateCSDL(List<FunctionImport> functionImportList, List<FunctionResult> functionResultList)
        {
            XDocument xdoc = XDocument.Load(Parameters.Csdl);
            XNamespace xns = xdoc.Root.GetDefaultNamespace();

            #region FunctionImports
            var ec = xdoc.Root
                .Descendants(xns + "EntityContainer")
                .FirstOrDefault();

            if (ec != null)
            {
                foreach (FunctionImport functionImport in functionImportList)
                {
                    var fi = ec
                                .Descendants(xns + "FunctionImport")
                                .Where(i => i.Attribute("Name").Value == functionImport.Name)
                                .FirstOrDefault();

                    //ha van már ilyen fv. import, akkor töröljük, majd hozzáadjuk az újat
                    if (fi != null)
                        fi.Remove();

                    XElement e = functionImport.GenerateXElement(xns);
                    ec.Add(e);
                }
            }
            #endregion

            #region FunctionResults
            foreach (FunctionResult functionResult in functionResultList)
            {
                var ct = xdoc.Root
                    .Descendants(xns + "ComplexType")
                    .Where(fr => fr.Attribute("Name").Value == functionResult.Name)
                    .FirstOrDefault();

                //ha már van ilyen ComplexType, akkor törli
                if (ct != null)
                    ct.Remove();

                xdoc.Root.Add(functionResult.GenerateXElement(xns));

            }
            #endregion

            xdoc.Save(Parameters.Csdl);
        }
        private void UpdateMSL(List<FunctionImportMapping> functionImportMappingList)
        {
            XDocument xdoc = XDocument.Load(Parameters.Msl);
            XNamespace xns = xdoc.Root.GetDefaultNamespace();
            var ecm = xdoc.Root
                .Descendants(xns + "EntityContainerMapping")
                .FirstOrDefault();

            if (ecm != null)
            {
                foreach (FunctionImportMapping functionImportMapping in functionImportMappingList)
                {
                    var fim = ecm
                                .Descendants(xns + "FunctionImportMapping")
                                .Where(m => m.Attribute("FunctionImportName").Value == functionImportMapping.FunctionImportName)
                                .FirstOrDefault();

                    //ha van már ilyen fv. import, akkor töröljük, majd hozzáadjuk az újat
                    if (fim != null)
                        fim.Remove();

                    XElement e = functionImportMapping.GenerateXElement(xns);
                    ecm.Add(e);
                }
            }
            xdoc.Save(Parameters.Msl);
        }

        private void BackupEdmx()
        {
            string backupName = Parameters.Edmx + Constants.BACKUP_EXT;
            if (File.Exists(backupName))
            {
                int i = 1;
                for (i = 1; i < 100; i++)
                {
                    if (!File.Exists(backupName + i.ToString()))
                        break;
                }
                backupName += i;
            }
            Logger.Instance.Log(Logger.LogType.Info, string.Format("edmx másolat {0} -> {1}", Parameters.Edmx, backupName));

            File.Copy(Parameters.Edmx, backupName);
        }
        private void UpdateEDMX(List<Function> functionList, List<FunctionImport> functionImportList, List<FunctionResult> functionResultList, List<FunctionImportMapping> functionImportMappingList)
        {
            Logger.Instance.Log(Logger.LogType.Info, "edmx file frissítés (functions, function results, mappings)...");
            XDocument edmxdoc = XDocument.Load(Parameters.Edmx);
            XNamespace xns = edmxdoc.Root.GetDefaultNamespace();
            XNamespace edmxNs = edmxdoc.Root.GetNamespaceOfPrefix("edmx");

            #region SSDL
            var storageModelsNode = edmxdoc.Root
                .Descendants(edmxNs + "StorageModels")
                .FirstOrDefault();

            if (storageModelsNode != null)
            {
                XElement schemaNode = storageModelsNode.Descendants().FirstOrDefault();
                XNamespace schemaNs = schemaNode.GetDefaultNamespace();

                foreach (Function function in functionList)
                {
                    var f = schemaNode
                                .Descendants(schemaNs + "Function")
                                .Where(m => m.Attribute("Name").Value == function.Name)
                                .FirstOrDefault();

                    if (f != null)
                        f.Remove();

                    schemaNode.Add(function.GenerateXElement(schemaNs));
                }
            }
            #endregion

            #region CSDL

            var conceptualModelsNode = edmxdoc.Root
                .Descendants(edmxNs + "ConceptualModels")
                .FirstOrDefault();

            if (conceptualModelsNode != null)
            {
                XElement schemaNode = conceptualModelsNode.Descendants().FirstOrDefault();
                XNamespace schemaNs = schemaNode.GetDefaultNamespace();

                #region FunctionImports
                var ec = schemaNode.Descendants(schemaNs + "EntityContainer")
                    .FirstOrDefault();

                if (ec != null)
                {
                    foreach (FunctionImport functionImport in functionImportList)
                    {
                        var fi = ec
                                    .Descendants(schemaNs + "FunctionImport")
                                    .Where(i => i.Attribute("Name").Value == functionImport.Name)
                                    .FirstOrDefault();

                        //ha van már ilyen fv. import, akkor töröljük, majd hozzáadjuk az újat
                        if (fi != null)
                            fi.Remove();

                        XElement e = functionImport.GenerateXElement(schemaNs);
                        ec.Add(e);
                    }
                }
                #endregion

                #region FunctionResults
                foreach (FunctionResult functionResult in functionResultList)
                {
                    var ct = schemaNode
                        .Descendants(schemaNs + "ComplexType")
                        .Where(fr => fr.Attribute("Name").Value == functionResult.Name)
                        .FirstOrDefault();

                    //ha már van ilyen ComplexType, akkor törli
                    if (ct != null)
                        ct.Remove();

                    schemaNode.Add(functionResult.GenerateXElement(schemaNs));

                }
                #endregion
            }
            #endregion

            #region MSL
            var mappingsNode = edmxdoc.Root
                .Descendants(edmxNs + "Mappings")
                .FirstOrDefault();
            if (mappingsNode != null)
            {
                var mappingNode = mappingsNode.Descendants().FirstOrDefault();
                if (mappingNode != null)
                {
                    var mappingNs = mappingNode.GetDefaultNamespace();
                    var ecm = mappingNode.Descendants(mappingNs + "EntityContainerMapping")
                        .FirstOrDefault();

                    if (ecm != null)
                    {
                        foreach (FunctionImportMapping functionImportMapping in functionImportMappingList)
                        {
                            var fim = ecm
                                        .Descendants(mappingNs + "FunctionImportMapping")
                                        .Where(m => m.Attribute("FunctionImportName").Value == functionImportMapping.FunctionImportName)
                                        .FirstOrDefault();

                            //ha van már ilyen fv. import, akkor töröljük, majd hozzáadjuk az újat
                            if (fim != null)
                                fim.Remove();

                            XElement e = functionImportMapping.GenerateXElement(mappingNs);
                            ecm.Add(e);
                        }
                    }
                }
            }
            #endregion

            edmxdoc.Save(Parameters.Edmx);

            //átnevezések
            StringBuilder edmxSB = new StringBuilder();
            using (TextReader tr = File.OpenText(Parameters.Edmx))
            {
                edmxSB.Append(tr.ReadToEnd());
            }
            File.Delete(Parameters.Edmx);

            /*
              <edmx:StorageModels>
      <Schema Namespace="RaktarModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
        <EntityContainer Name="RaktarModelStoreContainer">
             * 
             * 
             <edmx:ConceptualModels>
      <Schema Namespace="RaktarModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
        <EntityContainer Name="RaktarModelContext" annotation:LazyLoadingEnabled="true">
             * 
             * 
          <edmx:Mappings>
      <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
        <EntityContainerMapping StorageEntityContainer="RaktarModelStoreContainer" CdmEntityContainer="RaktarEntities">
          
             */

            string smEntityContainerName = "";
            string cmEntityContainerName = "";
            int index1, index2;
            string cont;

            string edmxContent = edmxSB.ToString();

            #region StorageModels
            //<edmx:StorageModels>
            //<Schema Namespace="RaktarModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
            //<EntityContainer Name="RaktarModelStoreContainer">
            index1 = edmxContent.IndexOf("<edmx:StorageModels>");
            if (index1 > -1)
            {
                index2 = edmxSB.ToString().IndexOf("</edmx:StorageModels>", index1);
                if (index2 > -1)
                {
                    cont = edmxSB.ToString().Substring(index1, index2 - index1);
                    if (Regex.IsMatch(cont, "<EntityContainer Name=\"(?<name>.*)\">"))
                    {
                        Match m = Regex.Match(cont, "<EntityContainer Name=\"(?<name>.*)\">");
                        smEntityContainerName = m.Groups["name"].Success ? m.Groups["name"].Value : "";
                    }
                }
            }
            #endregion StorageModels

            #region ConceptualModels
            //<edmx:ConceptualModels>
            //<Schema Namespace="RaktarModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
            //<EntityContainer Name="RaktarModelContext" annotation:LazyLoadingEnabled="true">
            index1 = edmxContent.IndexOf("<edmx:ConceptualModels>");
            if (index1 > -1)
            {
                index2 = edmxSB.ToString().IndexOf("</edmx:ConceptualModels>", index1);
                if (index2 > -1)
                {
                    cont = edmxSB.ToString().Substring(index1, index2 - index1);
                    if (Regex.IsMatch(cont, "<EntityContainer Name=\"(?<name>[^\\s]*)\""))
                    {
                        Match m = Regex.Match(cont, "<EntityContainer Name=\"(?<name>[^\\s]*)\"");
                        cmEntityContainerName = m.Groups["name"].Success ? m.Groups["name"].Value : "";
                    }
                }
            }
            #endregion ConceptualModels

            #region EntityContainerMapping
            //<edmx:Mappings>
            //<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
            //<EntityContainerMapping StorageEntityContainer="RaktarModelStoreContainer" CdmEntityContainer="RaktarEntities">
            edmxContent = Regex.Replace(edmxContent,
                "<EntityContainerMapping StorageEntityContainer=\"(?<StorageEntityContainer>[^\\s]*)\" CdmEntityContainer=\"(?<CdmEntityContainer>[^\\s]*)\">",
                string.Format("<EntityContainerMapping StorageEntityContainer=\"{0}\" CdmEntityContainer=\"{1}\">", smEntityContainerName, cmEntityContainerName));
            #endregion EntityContainerMapping

            //edmxSB = edmxSB.Replace("Debit3Model", "Debit3");
            //edmxSB = edmxSB.Replace("Debit3Context", "Debit3Entities");
            File.WriteAllText(Parameters.Edmx, edmxContent);

            Logger.Instance.Log(Logger.LogType.Info, "edmx file frissítés (functions, function results, mappings)...KÉSZ\n");
        }
        private void PrepareEdmx()
        {
            Logger.Instance.Log(Logger.LogType.Info, "edmx file feldolgozás...");
            XmlDocument doc;
            XmlNamespaceManager nsm;
            XmlNode node;
            
            XmlDocument edmxDoc = new XmlDocument();
            edmxDoc.Load(Parameters.Edmx);
            XmlNamespaceManager edmxNsm = new XmlNamespaceManager(edmxDoc.NameTable);
            edmxNsm.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2008/10/edmx");

            #region 1. edmx:StorageModels/Schema
            Logger.Instance.Log(Logger.LogType.Info, "\t1. lépés - storagemodels");
            edmxNsm.AddNamespace("ssdlschemans", "http://schemas.microsoft.com/ado/2009/02/edm/ssdl");
            var storageModelsSchemaNode = edmxDoc.SelectSingleNode("//edmx:StorageModels/ssdlschemans:Schema", edmxNsm);

            doc = new XmlDocument();
            doc.Load(Parameters.Ssdl);
            nsm = new XmlNamespaceManager(doc.NameTable);
            nsm.AddNamespace("ssdlns", NS_SSDL);

            node = doc.SelectSingleNode("//ssdlns:Schema", nsm);
            if ((storageModelsSchemaNode != null) && (node != null))
                storageModelsSchemaNode.InnerXml = node.InnerXml;
            #endregion

            #region 2. edmx:ConceptualModels/Schema
            Logger.Instance.Log(Logger.LogType.Info, "\t2. lépés - conceptualmodels");
            edmxNsm.AddNamespace("csdlschemans", "http://schemas.microsoft.com/ado/2008/09/edm");
            var conceptualModelsSchemaNode = edmxDoc.SelectSingleNode("//edmx:ConceptualModels/csdlschemans:Schema", edmxNsm);

            doc = new XmlDocument();
            doc.Load(Parameters.Csdl);
            nsm.AddNamespace("csdlns", NS_CSDL);

            node = doc.SelectSingleNode("//csdlns:Schema", nsm);
            if ((conceptualModelsSchemaNode != null) && (node != null))
                conceptualModelsSchemaNode.InnerXml = node.InnerXml;
            #endregion

            #region 3. edmx:Mappings/Mapping
            Logger.Instance.Log(Logger.LogType.Info, "\t3. lépés - mappings");
            edmxNsm.AddNamespace("mappingns", "http://schemas.microsoft.com/ado/2008/09/mapping/cs");
            var mappingNode = edmxDoc.SelectSingleNode("//edmx:Mappings/mappingns:Mapping/mappingns:EntityContainerMapping", edmxNsm);

            doc = new XmlDocument();
            doc.Load(Parameters.Msl);
            nsm = new XmlNamespaceManager(doc.NameTable);
            nsm.AddNamespace("mslns", NS_MSL);
            node = doc.DocumentElement.SelectSingleNode("mslns:EntityContainerMapping", nsm);
            if ((mappingNode != null) && (node != null))
            {
                Logger.Instance.Log(Logger.LogType.Info, "\t4. lépés - entityset mappings javítás");
                //a vs2010 edm designer nem támogatja az edmgen által generált entitysetmapping element-eket
                string mappings = FixMslEntitySetMappings(node.InnerXml);
                mappingNode.InnerXml = mappings;
            }
            #endregion

            Logger.Instance.Log(Logger.LogType.Info, "\t5. lépés - mentés...");
            edmxDoc.Save(Parameters.Edmx);

            Logger.Instance.Log(Logger.LogType.Info, "edmx file feldolgozás...KÉSZ\n");
        }
        private string FixMslEntitySetMappings(string mslContent)
        {
            //a vs2010 edm designer nem támogatja az edmgen által generált entitysetmapping element-eket
            //msl formátum,  pl.: 
            //<EntitySetMapping Name="Activity" StoreEntitySet="Activity" TypeName="Debit3.Activity">...</EntitySetMapping>
            //edm designer által várt formátum, pl.: 
            //  <EntitySetMapping Name="Activities">
            //      <EntityTypeMapping TypeName="Debit3Model.Activity">
            //          <MappingFragment StoreEntitySet="Activity">
            //...
            //          </MappingFragment>
            //      </EntityTypeMapping>
            //  </EntitySetMapping>
            string retval = Regex.Replace(mslContent,
                "<EntitySetMapping Name=\"(?<Name>[^\\s]*)\" StoreEntitySet=\"(?<StoreEntitySet>[^\\s]*)\" TypeName=\"(?<TypeName>[^\\s]*)\" xmlns=\"(?<xmlns>[^\\s]*)\">",
                "<EntitySetMapping Name=\"${Name}\" xmlns=\"${xmlns}\"><EntityTypeMapping TypeName=\"${TypeName}\"><MappingFragment StoreEntitySet=\"${StoreEntitySet}\">");
            retval = retval.Replace("</EntitySetMapping>", "</MappingFragment></EntityTypeMapping></EntitySetMapping>");
            return retval;
        }
        #endregion
    }
}
 
